//
//  MainView.m
//  V3d_Cocoa
//
//  Created by Y my on 11-3-14.
//  Copyright 2011 NJUST. All rights reserved.
//

#import "MainView.h"


@implementation MainView

@synthesize my4DImage, mainViewData;
@synthesize infoString;
//@synthesize disp_width, disp_height, disp_scale;
@synthesize disp_scale;
@synthesize pixmap;
@synthesize zoom_scale;
@synthesize translation;

- (void)setMainViewData:(MainViewData *)data {
	mainViewData = data;
	[mainViewData registerObserver:self];
}

- (void)setMy4DImage:(My4DImage *)data {
	my4DImage = data;
	[my4DImage registerObserver:self];
}

- (void)setPixmap:(CGImageRef)p {
	CGImageRelease(pixmap);
	pixmap = p;
	pixmap = CGImageRetain(pixmap);
}

- (void)setTranslation:(CGPoint)newtranslaton
{
	if(translation.x != newtranslaton.x)
		translation.x = newtranslaton.x;
	if(translation.y != newtranslaton.y)
		translation.y = newtranslaton.y;
}

- (BOOL)translationEqual:(CGPoint)newtranslaton
{
	return (translation.x == newtranslaton.x) && (translation.y == newtranslaton.y);
}
	
- (NSInteger)focusPlaneCoord {
	return cur_focus_ratio;
}

///////////////// init & dealloc ///////////////////

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
		NSLog(@"Init main view OK!");
		
    }
    return self;
}

- (void)awakeFromNib {
	disp_scale = 1;
	[self updateView];
}

- (void)dealloc {
	if (my4DImage) {
		[my4DImage unregisterObserver:self];
		[my4DImage release];
	}
	if (mainViewData) {
		[mainViewData unregisterObserver:self];
		[mainViewData release];
	}

	CGImageRelease(pixmap);
	[infoString release];
	
	[super dealloc];
}
/////////////// Observer /////////////////

- (void)updateView {
	if (!self.mainViewData || !self.my4DImage) {
		return;
	}
	
	// get data and redraw
	[self getSpecificData];
	//disp_width = self.bounds.size.width;
	//disp_height = self.bounds.size.height;
	[self setNeedsDisplay];
}

/////////////// main functions /////////////

- (void)getSpecificData {
	// this function MUST be overrided by subclasses.
}

- (void)drawRect:(CGRect)dirtyRect {
	
	CGRect viewBounds = [self bounds];
    // Drawing code here.
	CGContextRef theContext = UIGraphicsGetCurrentContext();

	CGContextSaveGState(theContext);
	
	// draw background
	[[UIColor cyanColor] set];
	CGContextBeginPath(theContext);
	CGContextAddRect(theContext, viewBounds);
	CGContextFillPath(theContext);
	
	// draw pixmap
	[self drawPixmapType:theContext];
	
	// draw info string
	CGFloat textSize = 16;
	CGRect r;
	r.origin.x = 1.0;
	r.origin.y = 1.0;
	r.size.height = textSize + 10;
	r.size.width = textSize + 10;
	CGContextBeginPath(theContext);
	CGContextAddEllipseInRect(theContext, r);
	CGContextFillPath(theContext);
	CGPoint drawpoint = {4, 4};
	[[UIColor redColor] set];
	[self.infoString drawAtPoint:drawpoint withFont:[UIFont systemFontOfSize:textSize]];
	
	CGContextRestoreGState(theContext);
}

- (void)drawPixmapType:(CGContextRef)theContext {
	
	if (self.pixmap == NULL) {
		return;
	}
	
	CGContextSaveGState(theContext);
	CGRect viewBounds = [self bounds];
	NSInteger disp_width = viewBounds.size.width;
	NSInteger disp_height = viewBounds.size.height;
    CGPoint center;
	center.x = disp_width/2.0;
	center.y = disp_height/2.0;
	
	curDisplayCenter = center;
	
	/*
	 
	 
	//for the un-zommed coordinate
    //painter->translate(center);
	CGContextTranslateCTM(theContext, center.x, center.y);
    
    //painter->scale(m_scale, m_scale);
	CGContextScaleCTM(theContext, m_scale, m_scale);
	//CGContextScaleCTM(theContext, 2, 2);
    
    //painter->translate(-center);
	CGContextTranslateCTM(theContext, -center.x, -center.y);
	
	//now zoom. 081114
    //painter->scale(disp_scale, disp_scale);
	CGContextScaleCTM(theContext, disp_scale, disp_scale);
	
	 
	 */

	CGContextTranslateCTM(theContext, self.translation.x, self.translation.y);
	
	CGContextTranslateCTM(theContext, center.x, center.y);
	CGContextScaleCTM(theContext, self.zoom_scale, self.zoom_scale);
	CGContextTranslateCTM(theContext, -center.x, -center.y);
	
	//CGContextTranslateCTM(theContext, self.mainViewData.translation.x, self.mainViewData.translation.y);	
	
	CGContextDrawImage(theContext, viewBounds, pixmap);
	

	/*
	if(self.my4DImage && [my4DImage isEmpty]==NO)
		b_displayFocusCrossLine = [my4DImage getFlagDisplayFocusCross];
	 */
	
	
	if (b_displayFocusCrossLine)
	{
		int focusPosInWidth, focusPosInHeight;
		if (![self getFocusCrossLinePosWidth:&focusPosInWidth andHeight:&focusPosInHeight]) //should be safe to call even my4DImage is NULL or contains no data
		{
			focusPosInWidth = disp_width/2.0;
			focusPosInHeight = disp_height/2.0;
		}
		
		[[UIColor yellowColor] set];
		CGFloat l[2] = {3, 3};
		CGContextSetLineDash(theContext, 0, l, 2);
		
		CGContextBeginPath(theContext);
		CGContextMoveToPoint(theContext, 0, [self bounds].size.height - focusPosInHeight);
		CGContextAddLineToPoint(theContext, [self bounds].size.width-1, [self bounds].size.height - focusPosInHeight);
		CGContextStrokePath(theContext);
		
		CGContextBeginPath(theContext);
		CGContextMoveToPoint(theContext, focusPosInWidth, 0);
		CGContextAddLineToPoint(theContext, focusPosInWidth, [self bounds].size.height-1);
		CGContextStrokePath(theContext);
	}
	
	/*
	if (my4DImage && !(my4DImage->isEmpty()))
	{
		if (my4DImage->getFlagLookingGlass())
		{
			setCursor(Qt::CrossCursor);
			
			
			// draw the Looking glass if necessary and possible. Note that when Looking glass is enabled, the m_scale is assumed to be 1
			drawLookingGlassMap(painter, 0); //draw the anchored zoom-in map
			if (bMouseCurorIn)
				drawLookingGlassMap(painter, &curMousePos); //draw the moving-point zoom-in map
		}
		else
		{
			setCursor(Qt::ArrowCursor);
		}
	}
	
	// draw the defined interesting & non-interesting points
	bool b_displaySelectedLocation=true;
	if (my4DImage && b_displaySelectedLocation==true)
	{
		drawSelectedLocations(painter, &(my4DImage->listLandmarks), &(my4DImage->listLocationRelationship));
	}
	
	// draw ROI
	drawROI(painter);
	 
	 */
	CGContextRestoreGState(theContext);
}

- (BOOL)getFocusCrossLinePosWidth:(int*)focusPosInWidth andHeight:(int*)focusPosInHeight {
	// must be implemented by subclasses
	return YES;
}

- (BOOL)internal_only_imgplane_op { // protected
	if (!self.my4DImage) return NO;
    ImagePixelType dtype;
  	unsigned char **** p4d = (unsigned char ****)[my4DImage getData:&dtype];
	if (!p4d) return NO;
	
	if (dtype==V3D_UINT8)
	{
		if ([my4DImage cDim]==1 && (Ctype==colorPseudoMaskColor || Ctype==colorArnimFlyBrainColor || Ctype==colorHanchuanFlyBrainColor))
		{
			if (my4DImage.colorMap)
			{
				self.pixmap = [self fillPixmapWithRawData_colormap:p4d
													   dtype:dtype
														 sz0:[my4DImage xDim]
														 sz1:[my4DImage yDim]
														 sz2:[my4DImage zDim]
														 sz3:[my4DImage cDim]
												   cposRatio:cur_focus_ratio
													colorMap:my4DImage.colorMap];
			}
			else
			{
				return NO;
			}
		}
		else
		{
			self.pixmap = [self fillPixmapWithRawData:p4d
											sz0:[my4DImage xDim]
											sz1:[my4DImage yDim]
											sz2:[my4DImage zDim]
											sz3:[my4DImage cDim]
										  ctype:Ctype
									  cposRatio:cur_focus_ratio
							   intensityRescale:self.mainViewData.flagImgValScaleDisplay
										 p_vmax:my4DImage.p_vmax
										 p_vmin:my4DImage.p_vmin];
		}
	}
	else if (dtype==V3D_UINT16)  // this part need to change in the future when I want to scale the UINT16 and display it as grayscale-256
	{
		if ([my4DImage cDim]==1)
		{
			if (my4DImage.colorMap && (Ctype==colorPseudoMaskColor || Ctype==colorArnimFlyBrainColor || Ctype==colorHanchuanFlyBrainColor))
			{
				self.pixmap = [self fillPixmapWithRawData_colormap:p4d
													   dtype:dtype
														 sz0:[my4DImage xDim]
														 sz1:[my4DImage yDim]
														 sz2:[my4DImage zDim]
														 sz3:[my4DImage cDim]
												   cposRatio:cur_focus_ratio
													colorMap:my4DImage.colorMap];
			}
			else
			{
				self.pixmap = [self fillPixmapWithRawData:p4d
												sz0:[my4DImage xDim]
												sz1:[my4DImage yDim]
												sz2:[my4DImage zDim]
												sz3:[my4DImage cDim]
											  ctype:Ctype
										  cposRatio:cur_focus_ratio
								   intensityRescale:self.mainViewData.flagImgValScaleDisplay
											 p_vmax:my4DImage.p_vmax
											 p_vmin:my4DImage.p_vmin];
			}
		}
		else
		{
			self.pixmap = [self fillPixmapWithRawData:p4d
											sz0:[my4DImage xDim]
											sz1:[my4DImage yDim]
											sz2:[my4DImage zDim]
											sz3:[my4DImage cDim]
										  ctype:Ctype
									  cposRatio:cur_focus_ratio
							   intensityRescale:self.mainViewData.flagImgValScaleDisplay
										 p_vmax:my4DImage.p_vmax
										 p_vmin:my4DImage.p_vmin];
		}
	}
	else if (dtype==V3D_FLOAT32)
	{
		if ([my4DImage cDim]==1)
		{
			if (my4DImage.colorMap && (Ctype==colorPseudoMaskColor || Ctype==colorArnimFlyBrainColor || Ctype==colorHanchuanFlyBrainColor))
			{
				self.pixmap = [self fillPixmapWithRawData_colormap:p4d
													   dtype:dtype
														 sz0:[my4DImage xDim]
														 sz1:[my4DImage yDim]
														 sz2:[my4DImage zDim]
														 sz3:[my4DImage cDim]
												   cposRatio:cur_focus_ratio
													colorMap:my4DImage.colorMap];
			}
			else
			{
				self.pixmap = [self fillPixmapWithRawData:p4d
												sz0:[my4DImage xDim]
												sz1:[my4DImage yDim]
												sz2:[my4DImage zDim]
												sz3:[my4DImage cDim]
											  ctype:Ctype
										  cposRatio:cur_focus_ratio
								   intensityRescale:self.mainViewData.flagImgValScaleDisplay
											 p_vmax:my4DImage.p_vmax
											 p_vmin:my4DImage.p_vmin];
			}
		}
		else
		{
			self.pixmap = [self fillPixmapWithRawData:p4d
											sz0:[my4DImage xDim]
											sz1:[my4DImage yDim]
											sz2:[my4DImage zDim]
											sz3:[my4DImage cDim]
										  ctype:Ctype
									  cposRatio:cur_focus_ratio
							   intensityRescale:self.mainViewData.flagImgValScaleDisplay
										 p_vmax:my4DImage.p_vmax
										 p_vmin:my4DImage.p_vmin];
		}
	}
	else
	{
		NSLog(@"Right now only support UINT8, UINT16, and FLOAT32.");
		return NO; //do nothing
	}
	
	return YES;
}

- (CGImageRef)fillPixmapWithRawData_colormap:(unsigned char****)p4d
								 dtype:(ImagePixelType)dtype
								   sz0:(V3DLONG)sz0
								   sz1:(V3DLONG)sz1
								   sz2:(V3DLONG)sz2
								   sz3:(V3DLONG)sz3
							 cposRatio:(CGFloat)cposRatio
							  colorMap:(ColorMap*)pc
{
	// must be implemented by subclasses
	return NULL;
}
						  
- (CGImageRef)fillPixmapWithRawData:(unsigned char****)p4d
						  sz0:(V3DLONG)sz0
						  sz1:(V3DLONG)sz1
						  sz2:(V3DLONG)sz2
						  sz3:(V3DLONG)sz3
						ctype:(ImageDisplayColorType)ctype
					cposRatio:(CGFloat)cposRatio
			 intensityRescale:(BOOL)bIntensityRescale
					   p_vmax:(double*)p_vmax
					   p_vmin:(double*)p_vmin
{
	// must be implemented by subclasses
	return NULL;
}
@end
